//
//  NSDate+YSExtension.m
//  YSKitExample
//
//  Created by Kyson on 2017/6/16.
//  Copyright © 2017年 YangShen. All rights reserved.
//

#import "NSDate+YSExtension.h"
#import <objc/runtime.h>

@implementation NSDateFormatter (YSExtension)

+ (instancetype)sharedDateFormatter {
    static NSDateFormatter *_df = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _df = [[NSDateFormatter alloc] init];
        [_df setLocale:[NSLocale currentLocale]];
        [_df setDateFormat:@"yyyy-MM-dd"];
    });
    return _df;
}

@end

static char *_components;

@implementation NSDate (YSExtension)

- (NSInteger)ys_year {
    return self.dateComponents.year;
}

- (NSInteger)ys_month {
    return self.dateComponents.month;
}

- (NSInteger)ys_day {
    return self.dateComponents.day;
}

- (NSInteger)ys_hour {
    return self.dateComponents.hour;
}

- (NSInteger)ys_minute {
    return self.dateComponents.minute;
}

- (NSInteger)ys_second {
    return self.dateComponents.second;
}

- (NSInteger)ys_nanosecond {
    return self.dateComponents.nanosecond;
}

- (NSInteger)ys_weekday {
    NSInteger weekday = self.dateComponents.weekday - 1;
    return weekday > 0 ?: 7 ;
}

- (NSInteger)ys_weekdayOrdinal {
    return self.dateComponents.weekdayOrdinal;
}

- (NSInteger)ys_weekOfMonth {
    return self.dateComponents.weekOfMonth;
}

- (NSInteger)ys_weekOfYear {
    return [[[NSCalendar currentCalendar] components:NSCalendarUnitWeekOfYear fromDate:self] weekOfYear];
}

- (NSInteger)ys_quarter {
    return [[[NSCalendar currentCalendar] components:NSCalendarUnitQuarter fromDate:self] quarter];
}

- (BOOL)ys_isLeapMonth {
    return [[[NSCalendar currentCalendar] components:NSCalendarUnitQuarter fromDate:self] isLeapMonth];
}

- (BOOL)ys_isLeapYear {
    NSUInteger year = self.ys_year;
    return ((year % 400 == 0) || ((year % 100 != 0) && (year % 4 == 0)));
}

- (NSString *)ys_lunarYear {
    NSInteger yearNumber = [self _lunarDateComponents].year - 1;
    NSArray *chineseYears = [NSArray arrayWithObjects:
                             @"甲子", @"乙丑", @"丙寅", @"丁卯", @"戊辰", @"己巳", @"庚午", @"辛未", @"壬申", @"癸酉",
                             @"甲戌", @"乙亥", @"丙子", @"丁丑", @"戊寅", @"己卯", @"庚辰", @"辛己", @"壬午", @"癸未",
                             @"甲申", @"乙酉", @"丙戌", @"丁亥", @"戊子", @"己丑", @"庚寅", @"辛卯", @"壬辰", @"癸巳",
                             @"甲午", @"乙未", @"丙申", @"丁酉", @"戊戌", @"己亥", @"庚子", @"辛丑", @"壬寅", @"癸丑",
                             @"甲辰", @"乙巳", @"丙午", @"丁未", @"戊申", @"己酉", @"庚戌", @"辛亥", @"壬子", @"癸丑",
                             @"甲寅", @"乙卯", @"丙辰", @"丁巳", @"戊午", @"己未", @"庚申", @"辛酉", @"壬戌", @"癸亥", nil];
    return chineseYears[yearNumber];
}

- (NSString *)ys_chineseZodial {
    NSInteger yearNumber = [self _lunarDateComponents].year % 12 - 1;
    yearNumber = yearNumber < 0 ? 11 : yearNumber;
    NSArray *chineseZodials = [NSArray arrayWithObjects:@"鼠", @"牛", @"虎", @"兔", @"龙", @"蛇", @"马", @"羊", @"猴", @"鸡", @"狗", @"猪", nil];
    return chineseZodials[yearNumber];
}

- (NSString *)ys_lunarMonth {
    NSInteger monthNumber = [self _lunarDateComponents].month - 1;
    NSArray *chineseMonths=[NSArray arrayWithObjects:
                            @"正月", @"二月", @"三月", @"四月", @"五月", @"六月", @"七月", @"八月",
                            @"九月", @"十月", @"冬月", @"腊月", nil];
    return chineseMonths[monthNumber];
}

- (NSString *)ys_lunarDay {
    NSInteger dayNumber = [self _lunarDateComponents].day - 1;
    NSArray *chineseDays = [NSArray arrayWithObjects:
                            @"初一", @"初二", @"初三", @"初四", @"初五", @"初六", @"初七", @"初八", @"初九", @"初十",
                            @"十一", @"十二", @"十三", @"十四", @"十五", @"十六", @"十七", @"十八", @"十九", @"二十",
                            @"廿一", @"廿二", @"廿三", @"廿四", @"廿五", @"廿六", @"廿七", @"廿八", @"廿九", @"三十",  nil];
    return chineseDays[dayNumber];
}

- (NSDateComponents *)dateComponents {
    NSDateComponents *dateComponents = objc_getAssociatedObject(self, &_components);
    if (!dateComponents) {
        dateComponents = [[NSCalendar currentCalendar] components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitWeekday | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond | NSCalendarUnitWeekdayOrdinal | NSCalendarUnitWeekOfMonth  fromDate:self];
        objc_setAssociatedObject(self, &_components, dateComponents, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return dateComponents;
}

- (NSDateComponents *)_lunarDateComponents {
    NSDateComponents *date = [[NSCalendar calendarWithIdentifier:NSCalendarIdentifierChinese] components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:self];
    return date;
}

- (NSDate *)ys_dateByAddingYears:(NSInteger)years {
    NSCalendar *calendar =  [NSCalendar currentCalendar];
    NSDateComponents *components = [[NSDateComponents alloc] init];
    [components setYear:years];
    return [calendar dateByAddingComponents:components toDate:self options:0];
}

- (NSDate *)ys_dateByAddingMonths:(NSInteger)months {
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *components = [[NSDateComponents alloc] init];
    [components setMonth:months];
    return [calendar dateByAddingComponents:components toDate:self options:0];
}

- (NSDate *)ys_dateByAddingWeeks:(NSInteger)weeks {
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *components = [[NSDateComponents alloc] init];
    [components setWeekOfYear:weeks];
    return [calendar dateByAddingComponents:components toDate:self options:0];
}

- (NSDate *)ys_dateByAddingDays:(NSInteger)days {
    NSTimeInterval aTimeInterval = [self timeIntervalSinceReferenceDate] + 86400 * days;
    NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
    return newDate;
}

- (NSDate *)ys_dateByAddingHours:(NSInteger)hours {
    NSTimeInterval aTimeInterval = [self timeIntervalSinceReferenceDate] + 3600 * hours;
    NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
    return newDate;
}

- (NSDate *)ys_dateByAddingMinutes:(NSInteger)minutes {
    NSTimeInterval aTimeInterval = [self timeIntervalSinceReferenceDate] + 60 * minutes;
    NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
    return newDate;
}

- (NSDate *)ys_dateByAddingSeconds:(NSInteger)seconds {
    NSTimeInterval aTimeInterval = [self timeIntervalSinceReferenceDate] + seconds;
    NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
    return newDate;
}

+ (NSString *)ys_todayWithFormat:(NSString *)format {
    return [[NSDate date] ys_stringWithFormat:format];
}

- (NSString *)ys_stringWithFormat:(NSString *)format {
    NSDateFormatter *formatter = [NSDateFormatter sharedDateFormatter];
    if(format) [formatter setDateFormat:format];
    return [formatter stringFromDate:self];
}

- (NSString *)ys_stringWithFormat:(NSString *)format timeZone:(NSTimeZone *)timeZone locale:(NSLocale *)locale {
    NSDateFormatter *formatter = [NSDateFormatter sharedDateFormatter];
    if(format) [formatter setDateFormat:format];
    if (timeZone) [formatter setTimeZone:timeZone];
    if (locale) [formatter setLocale:locale];
    return [formatter stringFromDate:self];
}

- (NSString *)ys_stringWithISOFormat {
    NSDateFormatter *formatter = [NSDateFormatter sharedDateFormatter];
    formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
    formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ssZ";
    return [formatter stringFromDate:self];
}

+ (NSDate *)ys_dateWithString:(NSString *)dateString format:(NSString *)format {
    NSDateFormatter *formatter = [NSDateFormatter sharedDateFormatter];
    if(format) [formatter setDateFormat:format];
    return [formatter dateFromString:dateString];
}

+ (NSDate *)ys_dateWithString:(NSString *)dateString format:(NSString *)format timeZone:(NSTimeZone *)timeZone locale:(NSLocale *)locale {
    NSDateFormatter *formatter = [NSDateFormatter sharedDateFormatter];
    if(format) [formatter setDateFormat:format];
    if (timeZone) [formatter setTimeZone:timeZone];
    if (locale) [formatter setLocale:locale];
    return [formatter dateFromString:dateString];
}

+ (NSDate *)ys_dateWithISOFormatString:(NSString *)dateString {
    NSDateFormatter *formatter = [NSDateFormatter sharedDateFormatter];
    formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
    formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ssZ";
    return [formatter dateFromString:dateString];
}

#pragma mark - 日期格式化
- (BOOL)ys_isThisYear {
    return [NSDate date].ys_year == self.ys_year;
}

- (BOOL)ys_isToday {
    if (fabs(self.timeIntervalSinceNow) >= 60 * 60 * 24) return NO;
    return [NSDate new].ys_day == self.ys_day;
}

- (BOOL)ys_isYesterday {
    NSDate *added = [self ys_dateByAddingDays:1];
    return [added ys_isToday];
}

+ (NSDateComponents *)ys_timeDifferenceComponentsFromDate:(NSDate *)startingDate toDate:(NSDate *)resultDate {
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSCalendarUnit unit = NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    return [calendar components:unit fromDate:startingDate toDate:resultDate options:0];
}

- (NSDateComponents *)ys_deltaWithNow {
    NSCalendar *calendar = [NSCalendar currentCalendar];
    int unit = NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    return [calendar components:unit fromDate:self toDate:[NSDate date] options:0];
}

+ (NSString *)ys_timeDifferenceStringFromDate:(NSDate *)startingDate toDate:(NSDate *)resultDate {
    NSInteger intevalTime = [resultDate timeIntervalSinceReferenceDate] - [startingDate timeIntervalSinceReferenceDate];
    
    // 分、时、天、月、年
    NSInteger minutes = intevalTime / 60;
    NSInteger hours   = intevalTime / 60 / 60;
    NSInteger day     = intevalTime / 60 / 60 / 24;
    NSInteger month   = intevalTime / 60 / 60 / 24 / 30;
    NSInteger yers    = intevalTime / 60 / 60 / 24 / 365;
    
    if (minutes <= 10) {
        return  @"刚刚";
    }else if (minutes < 60){
        return [NSString stringWithFormat: @"%ld分钟前",(long)minutes];
    }else if (hours < 24){
        return [NSString stringWithFormat: @"%ld小时前",(long)hours];
    }else if (day < 30){
        return [NSString stringWithFormat: @"%ld天前",(long)day];
    }else if (month < 12){
        NSDateFormatter * df =[[NSDateFormatter alloc]init];
        df.dateFormat = @"M月d日";
        NSString * time = [df stringFromDate:startingDate];
        return time;
    }else if (yers >= 1){
        NSDateFormatter * df =[[NSDateFormatter alloc]init];
        df.dateFormat = @"yyyy年M月d日";
        NSString * time = [df stringFromDate:startingDate];
        return time;
    }
    return @"";
}

@end

